/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package session.TX;

import entity.establishment.StakeholderFood;
import entity.establishment.OutletFood;
import entity.tx.*;
import entity.account.*;
import entity.establishment.Outlet;
import entity.establishment.Stakeholder;
import entity.tx.Cuisine;
import helper.tx.Helper_Outlet;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List; 
import java.util.Random;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

/**
 *
 * @author Chen Zhe, Lu Xiaodi
 */
@Stateless
public class OutletSB implements OutletSBRemote {

    @PersistenceContext()
    EntityManager em;

    public OutletSB() {
    }
    private static final String charset = "!0123456789abcdefghijklmnopqrstuvwxyz";

    public String getRandomString(int length) {
        Random rand = new Random(System.currentTimeMillis());
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int pos = rand.nextInt(charset.length());
            sb.append(charset.charAt(pos));
        }
        return sb.toString();
    }

//    public void createOutlet(Long stakeholderID, String outletName, String phoneNumber, String address, double latitude, double longitude) throws ExistException {
//        //remember to check for duplicate outlet 
//            //Create new OutletFood
//            StakeholderFood stakeholder = em.find(StakeholderFood.class, stakeholderID);
//            OutletFood outlet = new OutletFood();
//            outlet.create(outletName, phoneNumber, stakeholder, address);
//            outlet.setCreateTime(Calendar.getInstance());
//            
//            outlet.setLatitude(latitude);
//            outlet.setLongitude(longitude);
//            
//            stakeholder.addOutlet(outlet);   
//            em.persist(stakeholder);
//            em.persist(outlet);
//    }
    public String addNewOutlet(
            Long stakeholderID,
            Long socialID,
            double latitude,
            double longitude,
            String outletName,
            String blkNo,
            String streetName,
            String unitName,
            String postalCode,
            String phoneNo,
            String websiteURL,
            String email,
            String priceRange,
            String image,
            String buildingName,
            String operatingHrs) {

        //Check that the Stakeholder and Social exist
        Query q1 = em.createQuery("SELECT c FROM Stakeholder c WHERE c.id = :paramstakeholderID");
        q1.setParameter("paramstakeholderID", stakeholderID);

        Query q2 = em.createQuery("SELECT c FROM Social c WHERE c.id = :paramsocial");
        q2.setParameter("paramsocial", socialID);

        if (q1.getResultList().isEmpty()) {
            System.out.println("OutletSB: ERROR, Stakeholder not found");
            return "OutletSB: ERROR, Stakeholder not found";
        }
        Stakeholder outletOwner = (Stakeholder) q1.getResultList().get(0);

        if (q2.getResultList().isEmpty()) {
            System.out.println("OutletSB: ERROR, Social account not found");
            return "OutletSB: ERROR, Social account not found";
        }
        Social outletCreator = (Social) q2.getResultList().get(0);




        if (outletOwner.getClass() == StakeholderFood.class) {
            //Create the outlet and set the data fields
            OutletFood outlet = new OutletFood();

            outlet.setLatitude(latitude);
            outlet.setLongitude(longitude);
            outlet.setOutletName(outletName);
            outlet.setBlkNo(blkNo);
            outlet.setStreetName(streetName);
            outlet.setUnitName(unitName);
            outlet.setPostalCode(postalCode);
            outlet.setPhoneNo(phoneNo);
            outlet.setWebsiteURL(websiteURL);
            outlet.setEmail(email);
            outlet.setPriceRange(priceRange);
            outlet.setImage(image);
            outlet.setBuildingName(buildingName);
            outlet.setOperatingHrs(operatingHrs);

            outlet.setCreateTime(Calendar.getInstance());

            //Create the Places entity
            Places outletPlace = new Places();

            outletPlace.setPlaceName(outletName);
            outletPlace.setLatitude(latitude);
            outletPlace.setLongtitude(longitude);
            outletPlace.setCreator(outletCreator);
            outletPlace.setOutlet(outlet); 

            //Set the outlet to the Stakeholder
            StakeholderFood foodOutletOwner = em.find(StakeholderFood.class, stakeholderID);

            outlet.setStakeholder(foodOutletOwner);
            outlet.setPlaces(outletPlace);
            foodOutletOwner.addOutlet(outlet);

            em.persist(outlet);
            em.persist(outletPlace);
            em.flush();
            return "New Food Outlet created for " + foodOutletOwner.getName();
        }

        return "Error: Unable to determine what type of outlet to create!";

    }
    
    public String editOutlet(
            Long outletId,
            double latitude,
            double longitude,
            String outletName,
            String blkNo,
            String streetName,
            String unitName,
            String postalCode,
            String phoneNo,
            String websiteURL,
            String email,
            String priceRange,
            String image,
            String buildingName,
            String operatingHrs) {

        Outlet outlet = em.find (Outlet.class, outletId);
        
        if (outlet != null) {
            outlet.setLatitude(latitude);
            outlet.setLongitude(longitude);
            outlet.setOutletName(outletName);
            outlet.setBlkNo(blkNo);
            outlet.setStreetName(streetName);
            outlet.setUnitName(unitName);
            outlet.setPostalCode(postalCode);
            outlet.setPhoneNo(phoneNo);
            outlet.setWebsiteURL(websiteURL);
            outlet.setEmail(email);
            outlet.setPriceRange(priceRange);
            outlet.setImage(image);
            outlet.setBuildingName(buildingName);
            outlet.setOperatingHrs(operatingHrs);

            em.persist(outlet);
            em.flush();
            return "Outlet information successfully modified";
        }

        return "Error: Outlet does not exist!";

    }

    public void deleteOutlet(Long outletId) {
        //Find the outlet
        Outlet outletGeneric = em.find(Outlet.class, outletId);


        if (outletGeneric.getClass() == OutletFood.class) {
            OutletFood outlet = em.find(OutletFood.class, outletId);
            //Remove the outlet from the stakeholder
            StakeholderFood outletOwner = outlet.getStakeholder();
            outletOwner.getOutlets().remove(outlet);

            //Remove the outlet from the Places
            Places outletPlace = outlet.getPlaces();
            outletPlace.setOutlet(null);

            em.remove(outlet);
        }


    }

    public List<Cuisine> getAllCuisines() {
        List<Cuisine> returnList = new ArrayList<Cuisine>();
        Query q1 = em.createQuery("SELECT c FROM Cuisine c");

        return q1.getResultList();
    }

    public List<Cuisine> getCuisineByOutlet(Long outletID) {
        List<Cuisine> returnList = new ArrayList<Cuisine>();
        OutletFood outlet = em.find(OutletFood.class, outletID);

        return outlet.getCuisines();
    }

    public void changeOutletCuisine(Long outletID, List<String> cuisineList) {
        OutletFood outlet = em.find(OutletFood.class, outletID);
        
        List<Cuisine> newCuisines = new ArrayList<Cuisine>();
        
        for(String l : cuisineList){
            Cuisine c = em.find(Cuisine.class,l);
            newCuisines.add(c);
        }
        
        outlet.setCuisines(newCuisines);
        em.flush();
    }

    public List<OutletFood> getAllOutlets() {
        Query query = em.createQuery("SELECT o FROM OutletFood AS o");
        return query.getResultList();
    }

    public List<Helper_Outlet> getAllOutletsHelper() {
        List<OutletFood> list = this.getAllOutlets();
        if (list == null) {
            return null;
        }
        List<Helper_Outlet> returnList = new ArrayList<Helper_Outlet>();
        for (OutletFood o : list) {
            returnList.add(new Helper_Outlet(o.getId(), o.getOutletName(), o.getBlkNo(), o.getStreetName(),
                    o.getUnitName(), o.getPostalCode(),
                    o.getStakeholder().getName(), o.getPhoneNo(),o.getLeadTime_Day(),o.getLeadTime_Day()));
        }
        return returnList;
    }

    public String updateGeneralInfo(Long outletId, Double noShowFee, Boolean autoConfirm, Integer leadTime,
            Integer bookingWindow) {
        OutletFood outlet = em.find(OutletFood.class, outletId);
        if (outlet == null) {
            return "Outlet not found!";
        } else {
            outlet.setNoShowPenalty(noShowFee);
            outlet.setAutoConfirmReservation(autoConfirm);
            outlet.setLeadTime_Day(leadTime);
            outlet.setBookingWindow(bookingWindow);
            em.persist(outlet);
            em.flush();
            return "General information changed successfully!";
        }
    }

    public List<FoodItem> getFoodMenu(Long outletId) {
        OutletFood oe = em.find(OutletFood.class, outletId);
        if (oe == null) {
            return null;
        }

        return oe.getFoodMenu();
    }

    public List<FoodItem> getFeaturedFoodItems(Long outletId) {
        List<FoodItem> list = this.getFoodMenu(outletId);
        List<FoodItem> returnList = new ArrayList<FoodItem>();
        for (FoodItem l : list) {
            if (l.getType().equalsIgnoreCase("Featured Dish")) {
                returnList.add(l);
            }
        }
        return returnList;
    }

    public static String booleanToStr(Boolean b) {
        if (b) {
            return "yes";
        } else {
            return "no";
        }
    }

    public Boolean getAutoConfirm(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        if (out == null) {
            return null;
        }
        return out.getAutoConfirmReservation();
    }

    public Integer getLeadTime(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        if (out == null) {
            return null;
        }
        return out.getLeadTime_Day();
    }

    public Integer getBookingWindow(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        if (out == null) {
            return null;
        }
        return out.getBookingWindow();
    }

    public Double getNoShowPenalty(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        if (out == null) {
            return null;
        }
        return out.getNoShowPenalty();
    }

    public OutletFood getOutlet(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        return out;
    }

    public List<OutletFood> getSpecificOutlet(String o) {
        Query query = em.createQuery("SELECT OBJECT(e) FROM OutletFood e where LOCATE(:outletName, e.outletName)>0");
        query.setParameter("outletName", o);
        return query.getResultList();
    }

    public Long searchOutletIdByStr(String[] s) {
        Query query = em.createQuery("SELECT o FROM OutletFood o WHERE o.stakeholder.name = :value1"
                + " AND o.outletName= :value2");
        query.setParameter("value1", s[0].trim());
        query.setParameter("value2", s[1].trim());
        List<OutletFood> result = query.getResultList();
        if (result.size() != 1) {
            return null;
        } else {
            return result.get(0).getId();
        }
    }

    //added by Randall 13-oct-11 1245hrs
    public List<OutletFood> getOutletByStakeholder(String StakeholderName) {
        Query query = em.createQuery("SELECT c FROM OutletFood c where c.stakeholder.name = :paramStakeholder");
        query.setParameter("paramStakeholder", StakeholderName);
        return query.getResultList();
    }

    //Outlet Manager Codes by Randall
    //-----------------------------------------------------------------------------------------------------------
    public List<String> getOutletManagerEmailsbyOutlet(Long outletID) {
        //Find the outlet
        OutletFood outlet1 = em.find(OutletFood.class, outletID);
        if (outlet1 == null) {
            return null;
        }

        return outlet1.retrieveManagerEmailsAsList();
    }

    public String addManagerToOutlet(String managerEmail, Long outletID) {
        //Find the outlet
        OutletFood outlet1 = em.find(OutletFood.class, outletID);
        if (outlet1 == null) {
            return "The outlet does not exist.";
        }

        //Perform the addition
        String statusMSG = outlet1.addManager(managerEmail);

        em.flush();
        return statusMSG;
    }

    public String removeManagerFromOutlet(String managerEmail, Long outletID) {

        //Find the outlet
        OutletFood outlet1 = em.find(OutletFood.class, outletID);
        if (outlet1 == null) {
            return "The outlet does not exist.";
        }

        //Perform the removal
        String statusMSG = outlet1.removeManager(managerEmail);

        em.flush();
        return statusMSG;
    }

    public List<OutletFood> retrieveOutletsByManager(String email) {
        List<OutletFood> returnList = new ArrayList<OutletFood>();

        String queryString = "SELECT c FROM OutletFood c WHERE LOWER(c.managerEmails) LIKE '%" + email.toLowerCase() + "%'";
        System.out.println(">>>>>>>>>>>>>> " + queryString);
        Query q = em.createQuery(queryString);


        return q.getResultList();
    }

    public String getStakeholderName(Long outletId) {
        OutletFood out = em.find(OutletFood.class, outletId);
        if (out == null) {
            return null;
        } else {
            return out.getStakeholder().getName();
        }
    }
    //End OutletFood Manager Codes
    //-----------------------------------------------------------------------------------------------------------
}
